`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: James Forrest
// 
// Create Date:    20:34:56 09/10/2013 
// Design Name: 
// Module Name:    HexKeypad 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module HexKeypadDecoder(input        clk_50,
                        inout  [7:0] pmodPort,
                        output       pressedFlag, // this is true when a button is pressed
                        output [3:0] pressedData  // this is valid when pressedFlag is true
                        );

    // have a count register to allow scanning every 4ms
    reg [18:0] clk_count;
    
    // wire ports to useful signals
    wire [3:0] row = pmodPort[7:4];
    reg  [3:0] col;
    assign     pmodPort[3:0] = col;
    // define output signals
    reg  [3:0] res;
    reg  [3:0] down;
    assign pressedFlag = |down;
    assign pressedData = res;

    // initialise
    initial begin
        clk_count <= 19'b0;
        col <= 3'b0;
    end

    always @ (posedge clk_50) begin
        // increment counter
        clk_count <= clk_count + 1;
        // check counter
        case(clk_count)
            19'b0001100001101010000: col <= 4'b0111;     // 1.00000 ms
            19'b0001100001101011000: begin down[3] <= 1'b1;
                                         case(row)       // 1.00016 ms
                                            4'b0111: res <= 4'h1;     // 1
                                            4'b1011: res <= 4'h4;     // 4
                                            4'b1101: res <= 4'h7;     // 7
                                            4'b1110: res <= 4'h0;     // 0
                                            default: down[3] <= 1'b0;
                                     endcase end
            19'b0011000011010100000: col <= 4'b1011;     // 2.00000 ms
            19'b0011000011010101000: begin down[2] <= 1'b1;
                                         case(row)       // 2.00016 ms
                                            4'b0111: res <= 4'h2;     // 2
                                            4'b1011: res <= 4'h5;     // 5
                                            4'b1101: res <= 4'h8;     // 8
                                            4'b1110: res <= 4'hF;     // F
                                            default: down[2] <= 1'b0;
                                     endcase end
            19'b0110000110101000000: col <= 4'b1101;     // 3.00000 ms
            19'b0110000110101001000: begin down[1] <= 1'b1;
                                         case(row)       // 3.00016 ms
                                            4'b0111: res <= 4'h3;     // 3
                                            4'b1011: res <= 4'h6;     // 6
                                            4'b1101: res <= 4'h9;     // 9
                                            4'b1110: res <= 4'hE;     // E
                                            default: down[1] <= 1'b0;
                                     endcase end
            19'b1100001101010000000: col <= 4'b1110;     // 4.00000 ms
            19'b1100001101010001000: begin down[0] <= 1'b1;
                                        case(row)        // 4.00016 ms
                                             4'b0111: res <= 4'hA; // A
                                             4'b1011: res <= 4'hB; // B
                                             4'b1101: res <= 4'hC; // C
                                             4'b1110: res <= 4'hD; // D
                                             default: down[0] <= 1'b0;
                                         endcase
                                         clk_count <= 19'd0; // reset to 0ms
                                     end
        endcase
    end

endmodule
